﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using PessModel;
using System.IO;
using System.Web.Security;
using System.Reflection;
using DynamicQueryLib;
using LinqKit;
using PessMvc.Models;
using System.Diagnostics;
using System.Web.UI.WebControls;
using System.Web.UI;
using System.Text;
using DoddleReport;
using DoddleReport.Web;
using System.Collections;
using System.Globalization;
using System.Resources;
using System.Web.Profile;
using PessMvc.Helpers;
using LinqToExcel;
using LinqToExcel.Domain;
using PessMvc.Lib;
using Ionic.Zip;
using System.Data.Entity.Validation;

namespace PessMvc.Controllers
{
    [Authorize]
    public class ArchiveController : Controller
    {
        private PESSEntities db;
        private IArchiveBL ibl;

        public ArchiveController()
        {
            ibl= new ArchiveBL(this.ModelState);
            db = new PESSEntities();
        }
        //
        // GET: /Archive/

        public ActionResult Index(int activityID,int subjectID=-1,string keyword="",int page=1,int archiveID=-1)//return to the correct page
        {
            ViewData["ActivityID"] = activityID;
            ViewBag.SubjectID = new SelectList(db.Subjects.Where(s => s.ActivityID == activityID), "ID", "Name");
            ViewBag.SelectedSubjectID = subjectID;
            
            var activity=db.Activities.Find(activityID);
            ViewBag.IsArchiveModificationAllowed = Utility.IsArchiveModificationAllowed(activity, new ModelStateDictionary());//Don't want to show error message.
            ViewBag.HideArchiveDetails = activity.HideArchiveDetails;

            IQueryable<Archive> archives;
            if (keyword.Trim() == "")//not searching by keyword
            {
                archives = db.Archives.Include(a => a.Subject).Include(a => a.County).Where(a => a.Subject.ActivityID == activityID);

                string userName = Membership.GetUser().UserName;
                if (Roles.IsUserInRole(Membership.GetUser().UserName, "ExpertJudge"))
                {
                    int exptSubjectID = db.ExpertJudges.Find(userName).ExpertGroup.Subject.ID;
                    archives = archives.Where(a => a.SubjectID == exptSubjectID);
                }
                else
                {
                    if (subjectID >= 0)
                    {
                        archives = archives.Where(a => a.SubjectID == subjectID);
                    }
                }
                if (Roles.IsUserInRole("CountyAdmin"))
                {
                    ProfileBase profile = ProfileBase.Create(userName);
                    string countyCode = (string)profile["CountyCode"];
                    archives = archives.Where(a => a.CountyCode.Trim() == countyCode.Trim());
                }
            }
            else//search by keyword
            {
                archives=Search(activityID, keyword);
            }
            archives=archives.OrderBy(a => a.SubjectID).ThenBy(a => a.CountyCode);

            PageInfo pageInfo = new PageInfo();
            pageInfo.TotalItems = archives.Count();
            pageInfo.ItemsPerPage = 20;
            if (archiveID >= 1)
            {
                int index = archives.ToList().Select((a, i) => new { Archive = a, Index = i }).First(a => a.Archive.ID == archiveID).Index;
                pageInfo.CurrentPage = index / pageInfo.ItemsPerPage + 1;
            }
            else
            {
                pageInfo.CurrentPage = page;
            }

            ArchivesModel model = new ArchivesModel(archives
                .Skip((pageInfo.CurrentPage - 1) * pageInfo.ItemsPerPage).Take(pageInfo.ItemsPerPage)//paging
                .ToList());
            model.PageInfo = pageInfo;
            model.ActivityID = activityID;
            model.SubjectID = subjectID;
            model.Keyword = keyword;

            return View(model);
        }

        private IQueryable<Archive> Search(int activityID, string keyword)
        {
            keyword = keyword.Trim();
            //Get string type properties from Archive
            var properties = GetArchiveProperties<Archive>();
            //Prepare the filters
            List<DynamicQueryLib.Filter> filterList = new List<DynamicQueryLib.Filter>();
            for (int i=0;i<properties.Count;i++)// var prop in properties)
            {
                DynamicQueryLib.Filter f = new DynamicQueryLib.Filter();
                if (i == 0)
                {
                    f.Connector = FilterConnectorType.AND;//the first connector must be AND, otherwise, you get a true
                }
                else
                {
                    f.Connector = FilterConnectorType.OR;
                }
                f.PropertyName = properties[i].Name;
                f.PropertyType = typeof(string);
                f.Values.Add(keyword);
                f.Operator = RelationalOperators.Contains;
                filterList.Add(f);
            }
            var predicate = LambdaExpressionHelper<Archive>.CreatePredicate<Archive>(filterList);
            var activityArchives = db.Archives.AsExpandable().Where(a => a.Subject.ActivityID == activityID);
            var archives =activityArchives.Where(predicate);
            archives=archives.Union(activityArchives.Include("Subject").Include("County").Where(a=>a.Subject.Name.Contains(keyword)||a.County.Name.Contains(keyword)));

            //restrict search result according to user role
            string userName = Membership.GetUser().UserName;
            if (Roles.IsUserInRole(userName, "ExpertJudge"))
            {
                int exptSubjectID = db.ExpertJudges.Find(userName).ExpertGroup.Subject.ID;
                archives = archives.Where(a => a.SubjectID == exptSubjectID);
            }
            //else
            //{
            //    if (subjectID >= 0)
            //    {
            //        archives = archives.Where(a => a.SubjectID == subjectID);
            //    }
            //}
            if (Roles.IsUserInRole("CountyAdmin"))
            {
                ProfileBase profile = ProfileBase.Create(userName);
                string countyCode = (string)profile["CountyCode"];
                archives = archives.Where(a => a.CountyCode.Trim() == countyCode.Trim());
            }
            //return View(archives);
            return archives;
        }

        private List<PropertyInfo> GetArchiveProperties<T>()
        {
            var properties = typeof(T).GetProperties(BindingFlags.DeclaredOnly
                                                           | BindingFlags.Public
                                                           | BindingFlags.Instance)
                                                           .Where(p => p.PropertyType == typeof(string) && p.Name != "CalculatedSerialNumber").ToList();
            return properties;
        }
        //
        // GET: /Archive/Details/5

        public ActionResult Details(int id)
        {
            Archive archive = db.Archives.Find(id);
            if (archive.SerialNumber==null||archive.SerialNumber.Trim() == "")
            {
                archive.SerialNumber = archive.CalculatedSerialNumber;
            }
            if (archive == null)
            {
                return HttpNotFound();
            }
            if (!Utility.IsUserAllowedtoOpenArchive(archive, Membership.GetUser()))
            {
                return HttpNotFound();
            }

            ViewBag.IsArchiveModificationAllowed = Utility.IsArchiveModificationAllowed(archive.Subject.Activity, new ModelStateDictionary());//Don't want to show error message.
            ViewBag.IsScoreInputAllowed = Utility.IsScoreInputAllowed(archive.Subject.Activity, new ModelStateDictionary());//Don't want to show error message.
            ViewBag.HideArchiveDetails = archive.Subject.Activity.HideArchiveDetails;
            //ViewBag.ReturnUrl = returnUrl;
            return View(archive);
        }



        //
        // GET: /Archive/Create

        public ActionResult Create(int activityID)
        {
            ViewBag.ActivityID = activityID;//new SelectList(db.Activities, "ID", "Name");
            ViewBag.SubjectID = new SelectList(db.Subjects.Where(s=>s.ActivityID==activityID), "ID", "Name");
            ViewBag.CountyCode = new SelectList(GetCounties(), "Code", "Name");
            ViewBag.Gender = Utility.GenderSelectList(true);

            return View();
        }
        private IQueryable<County> GetCounties()
        {
            IQueryable<County> counties = null;
            MembershipUser user = Membership.GetUser();
            if (Roles.IsUserInRole(user.UserName, "CountyAdmin"))
            {
                ProfileBase profile = ProfileBase.Create(user.UserName);
                string countyCode = (string)profile["CountyCode"];
                counties = db.Counties.Where(c => c.Code == countyCode);
            }
            else if (Roles.IsUserInRole(user.UserName, "Admin"))
            {
                counties = db.Counties;
            }
            return counties;
        }
        //
        // POST: /Archive/Create

        [HttpPost]
        public ActionResult Create(Archive archive,int activityID)
        {
            //if (!ModelState.IsValid)
            //{
            //    return View(archive);
            //}
            //ViewBag.ActivityID = db.Subjects.Find(archive.SubjectID).ActivityID;
            //int acitivityID=(int)ViewBag.ActivityID;
            //archive.Subject = db.Subjects.Find(archive.SubjectID);

            ViewBag.ActivityID = activityID;
            ViewBag.SubjectID = new SelectList(db.Subjects.Where(s => s.ActivityID ==activityID), "ID", "Name", archive.SubjectID);
            ViewBag.CountyCode = new SelectList(GetCounties(), "Code", "Name");
            ViewBag.Gender = Utility.GenderSelectList(archive.Gender);

            int quotaLimit = 0;
            var quota = db.CandidateQuotas.Find(archive.SubjectID, archive.CountyCode);
            if (quota == null) { quotaLimit = 0; }
            else
            {
                quotaLimit = Convert.ToInt32(quota.Quota);
            }
            if (quota!=null&&db.Archives.Where(a => a.CountyCode == quota.CountyCode && a.SubjectID == quota.SubjectID).Count() < quotaLimit)
            {
                //Add archive to database
                if (ModelState.IsValid)
                {
                    //Make sure the previousSN and the current one are of the same county.
                    Archive preArchive=db.Archives.Where(a => a.SerialNumber == archive.PreviousSN).FirstOrDefault();
                    if (archive.PreviousSN==null //Archive has no previous archive.
                        ||preArchive != null && preArchive.CountyCode == archive.CountyCode //Previous archive and the current one belong to the same county.
                        )
                    {
                        try
                        {
                            db.Archives.Add(archive);
                            db.SaveChanges();
                        }
                        catch (DbEntityValidationException e)
                        {
                            foreach (var eve in e.EntityValidationErrors)
                            {
                                Debug.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
                                    eve.Entry.Entity.GetType().Name, eve.Entry.State);
                                foreach (var ve in eve.ValidationErrors)
                                {
                                    Debug.WriteLine("- Property: \"{0}\", Error: \"{1}\"",
                                        ve.PropertyName, ve.ErrorMessage);
                                }
                            }
                            throw;
                        }
                        //int activityID = db.Subjects.Where(s => s.ID == archive.SubjectID).SingleOrDefault().ActivityID;

                        //Set archive's serialnumber
                        db.Entry(archive).Reference(e=>e.Subject).Load();
                        archive.SerialNumber = string.Format("Y{0}A{1}S{2}V{3}",
                            archive.Subject.Activity.AdminYear.Value.Year,
                            archive.Subject.ActivityID,
                            archive.SubjectID,
                            archive.ID
                        );
                        db.Entry(archive).State = EntityState.Modified;
                        db.SaveChanges();

                        //存放申报表
                        this.SaveArchiveFormToFolder(activityID, archive);

                        return RedirectToAction("Details", new { id = archive.ID });
                    }
                    else
                    {
                        ModelState.AddModelError(string.Empty, "历史档案不存在，或者非本区档案！");
                    }                    
                }

                //ViewBag.ActivityID = new SelectList(db.Activities, "ID", "Name", archive.Subject.ActivityID);

                return View(archive);
            }
            else
            {
                string errorMsg = "";
                if (quota != null)
                {
                    errorMsg = string.Format("{0}({1}区)的配额已满！", quota.Subject.Name, quota.County.Name);
                }
                else
                {
                    errorMsg = string.Format("配额不存在！");
                }
                ModelState.AddModelError(string.Empty,errorMsg );
                return View(archive);
            }
        }

        //
        // GET: /Archive/Edit/5

        public ActionResult Edit(int id)
        {
            Archive archive = db.Archives.Find(id);

            if (archive.SerialNumber==null||archive.SerialNumber.Trim() == "")
            {
                archive.SerialNumber = archive.CalculatedSerialNumber;
            }

            if (archive == null)
            {
                return HttpNotFound();
            }
            ViewBag.ActivityID = new SelectList(db.Activities, "ID", "Name", archive.Subject.ActivityID);
            ViewBag.SubjectID = new SelectList(db.Subjects.Where(s=>s.ActivityID==archive.Subject.ActivityID) , "ID", "Name", archive.SubjectID);
            ViewBag.Gender = Utility.GenderSelectList(archive.Gender);
            return View(archive);
        }

        //
        // POST: /Archive/Edit/5

        [HttpPost]
        public ActionResult Edit(Archive archive)
        {
            if (ModelState.IsValid)
            {
                db.Entry(archive).State = EntityState.Modified;
                db.SaveChanges();

                //if (archive.SerialNumber == null || archive.SerialNumber.Trim() == "")
                //{
                //    archive.SerialNumber = archive.CalculatedSerialNumber;
                //}
                //db.SaveChanges();

                int activityID = db.Subjects.Find(archive.SubjectID).ActivityID;
                //存放申报表。
                this.SaveArchiveFormToFolder(activityID,archive);

                //return RedirectToAction("Index", new {ActivityID=activityID });
                return RedirectToAction("Details", new { id = archive.ID });
            }
            ViewBag.ActivityID = new SelectList(db.Activities, "ID", "Name", archive.Subject.ActivityID);
            ViewBag.SubjectID = new SelectList(db.Subjects, "ID", "Name", archive.SubjectID);
            ViewBag.Gender = Utility.GenderSelectList(archive.Gender);

            return View(archive);
        }

        /// <summary>
        /// Save the apply form information into a file, then put into the archive folder.
        /// </summary>
        /// <param name="activityID"></param>
        /// <param name="archive"></param>
        private void SaveArchiveFormToFolder(int activityID,Archive archive)
        {
            //
            //1).Get properties from GetArchiveList_Result
            var propertInfos = GetArchiveProperties<GetArchiveList_Result>();
            List<ArchiveProperty> archPropList = new List<ArchiveProperty>();
            for (int i = 0; i < propertInfos.Count; i++)
            {
                archPropList.Add(new ArchiveProperty() { Id = i, Name = propertInfos[i].Name, LocalName = Utility.Translate<PessResources.Archive>(propertInfos[i].Name) });
            }
            //2).Get archive, for report saving.
            var archive1 = db.GetArchiveList(activityID).Where(a => a.SerialNumber == archive.SerialNumber).FirstOrDefault();
            //3).Don't want these properties in the info report.
            string[] excludedProperties = new string[] { "ReviewFeedback", "Conclusion", "ProjectSN", "CountyCode" };
            archPropList = (from p in archPropList
                            where !excludedProperties.Contains(p.Name)
                            select p).ToList();
            foreach (var p in archPropList)
            {
                p.Value = (string)GetPropValue(archive1, p.Name);
            }
            //4).send archPropList to doddle report.
            string path = Path.Combine(Server.MapPath("~/App_Data/Archives/"), activityID.ToString(), archive.ID.ToString());//, "申报表.xls"
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            string fullFilePath = Path.Combine(path, "申报表.xls");
            IReportWriter writer = new DoddleReport.Writers.ExcelReportWriter();
            var report = CreateReport(archPropList.ToList(), new string[] { "LocalName", "Value" },"申报表",archive.Subject.Activity.Name,archive.TeacherName);
            using (FileStream fs = System.IO.File.Create(fullFilePath))
            {
                writer.WriteReport(report, fs);
            } 
        }

        private object GetPropValue(object src, string propName)
        {
            return src.GetType().GetProperty(propName).GetValue(src, null);
        }
        //
        // GET: /Archive/Delete/5

        public ActionResult Delete(int id = 0)
        {
            Archive archive = db.Archives.Find(id);
            if (archive == null)
            {
                return HttpNotFound();
            }
            return View(archive);
        }

        //
        // POST: /Archive/Delete/5

        [HttpPost, ActionName("Delete")]
        public ActionResult DeleteConfirmed(int id)
        {
            int activityID;
            Archive archive = db.Archives.Find(id);
            activityID = archive.Subject.ActivityID;

            //archive has attachments. delete them.
            if (archive.Attachments.Count > 0)
            {
                var attachments=archive.Attachments.ToList();
                foreach (var a in attachments)
                {
                    archive.Attachments.Remove(a);
                }
                db.SaveChanges();
            }

            //archive has scores. delete them.
            if (archive.Scores.Count > 0)
            {
                var scores = archive.Scores.ToList();
                foreach (var s in scores)
                {
                    archive.Scores.Remove(s);
                }
                db.SaveChanges();
            }

            db.Archives.Remove(archive);
            db.SaveChanges();
            
            return RedirectToAction("Index", new {activityID=activityID });
        }

        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }

        [HttpPost]
        public ActionResult UploadAttachment(HttpPostedFileBase file, int archiveID)
        {
            int? activityID=db.Archives.Find(archiveID).Subject.ActivityID;

            // Verify that the user selected a file
            if (file != null && file.ContentLength > 0)
            {
                // extract only the fielname
                var fileName = Path.GetFileName(file.FileName);
                // store the file inside ~/App_Data/uploads folder
                var path = Path.Combine(Server.MapPath("~/App_Data/Archives/"),activityID.ToString(),archiveID.ToString());
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }

                file.SaveAs(Path.Combine(path,fileName));                
            }

            return RedirectToAction("Details", "Archive", new { id = archiveID });
        }

        public string Upload(HttpPostedFileBase fileData, int archiveID)
        {
            //var fileName = this.Server.MapPath("~/uploads/" + System.IO.Path.GetFileName(file.FileName));
            //file.SaveAs(fileName);

            int? activityID = db.Archives.Find(archiveID).Subject.ActivityID;

            // Verify that the user selected a file
            if (fileData != null && fileData.ContentLength > 0)
            {
                // extract only the fielname
                var fileName = Path.GetFileName(fileData.FileName);
                // store the file inside ~/App_Data/uploads folder
                var path = Path.Combine(Server.MapPath("~/App_Data/Archives/"), activityID.ToString(), archiveID.ToString());
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }

                fileData.SaveAs(Path.Combine(path, fileName));

                //Add attachment info to db.
                Archive archive = db.Archives.Find(archiveID);
                //Attachment doesn't exist.
                if (archive.Attachments.Where(a => a.Title == fileName).Count() <= 0)
                {
                    FileInfo fileInfo = new FileInfo(Path.Combine(path, fileName));
                    archive.Attachments.Add(new Attachment { Title = fileName, ArchiveID = archiveID, FilePath = path, TimeStamp = fileInfo.CreationTime, FileSize = (int)(fileInfo.Length / 1024) });
                    db.SaveChanges();
                }
                else
                {//Attachment exits.
                    Attachment attachment = archive.Attachments.Where(a => a.Title == fileName).SingleOrDefault();
                    FileInfo fileInfo = new FileInfo(Path.Combine(path, fileName));
                    attachment.FileSize = (int)(fileInfo.Length / 1024);
                    attachment.TimeStamp = fileInfo.CreationTime;
                    db.Entry(attachment).State = EntityState.Modified;
                    db.SaveChanges();
                }
            }

            return "ok";
        }

        [Authorize(Roles="Admin,CountyAdmin")]
        public ActionResult DeleteAttachment(int archiveID, string title)
        {
            var attachment = db.Attachments.Where(a => a.ArchiveID == archiveID && a.Title.Trim() == title.Trim()).FirstOrDefault();
            return View(attachment);
        }

        [HttpPost, ActionName("DeleteAttachment")]
        [Authorize(Roles = "Admin,CountyAdmin")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteDeleteAttachmentConfirmed(int archiveID, string title)
        {
            Attachment attachment = db.Attachments.Find(archiveID, title);
            string fullName = Path.Combine(attachment.FilePath, attachment.Title);//Title is filename
            try
            {
                System.IO.File.Delete(fullName);
            }
            catch { }
            finally
            {
                db.Attachments.Remove(attachment);
                db.SaveChanges();
            }
            return RedirectToAction("Details", "Archive", new { id = archiveID });
        }

        public FileResult Download(int archiveID, string title)
        {
            Attachment attachment=db.Attachments.Find(archiveID,title);
            string fullName=Path.Combine(attachment.FilePath,attachment.Title);//Title is filename
            byte[] fileBytes = PessMvc.Helpers.Utility.GetFile(fullName);
            return File(fileBytes,System.Net.Mime.MediaTypeNames.Application.Octet,title);
        }

        public ActionResult UploadPhoto(HttpPostedFileBase file, int archiveID)
        {
            if (file != null && file.ContentLength > 0)
            {
                var archive = db.Archives.Find(archiveID);
                string fileName = Path.GetFileName(file.FileName);
                int? activityID = db.Archives.Find(archiveID).Subject.ActivityID;
                var path = Path.Combine(Server.MapPath("~/uploads/"), activityID.ToString(), archiveID.ToString());
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }

                file.SaveAs(Path.Combine(path, fileName));

                //Add attachment info to db.
                archive.PhotoUrl = fileName;
                db.Entry(archive).State = EntityState.Modified;
                db.SaveChanges();
            }
            return RedirectToAction("Edit", "Archive", new { id = archiveID });
        }

        //public string GetPhotoUrl(int archiveID)
        //{
        //    db.Archives.Find(archiveID);UrlHelper.GenerateContentUrl(
        //}

        /// <summary>
        /// 
        /// </summary>
        /// <param name="archiveID">Current archive id.</param>
        /// <returns></returns>
        public ActionResult PreviousArchives(int archiveID)
        {
            string previousSN=db.Archives.Find(archiveID).PreviousSN;
            ViewBag.ArchiveID = archiveID;
            if(previousSN!=null&&previousSN.Trim()!="")
            {
                List<PreviousArchiveModel> archives = new List<PreviousArchiveModel>();
                FindPrevArchive(previousSN, ref archives);
                //var previousArchive = db.Archives.ToList().Where(a => a.SerialNumber ==previousSN ).FirstOrDefault();                
                return View(archives);
            }
            else
            {
                return View();
            }
        }

        private Archive FindPrevArchive(string serialNumber, ref List<PreviousArchiveModel> archives)
        {
            Archive archive = db.Archives.Where(a => a.SerialNumber.Trim() == serialNumber.Trim()).FirstOrDefault();
            if (archive == null)
            {
                return null;
            }
            archives.Add(new PreviousArchiveModel() { ActivityName = archive.Subject.Activity.Name, ArchiveID = archive.ID, SerialNumber = archive.SerialNumber, TeacherName = archive.TeacherName });

            if (archive.PreviousSN==null||archive.PreviousSN.Trim() == "")//End case
            {                
                return archive;
            }
            else //Recurrive case
            {
                return FindPrevArchive(archive.PreviousSN, ref archives);
            }
        }

        public ActionResult PreviousArchiveDetails(int archiveID, int backtoID)
        {
            var archive = db.Archives.Find(archiveID);
            ViewBag.BackToID = backtoID;
            return View(archive);
        }

        public ActionResult ExportArchiveList(int activityID, List<ArchiveProperty> properties, int subjectID = -1)
        {
            List<string> selectedPropertyList = new List<string>();
            if (properties != null)
            {
                foreach (var p in properties)
                {
                    if (p.IsSelected)
                    {
                        //Debug.WriteLine("Property {0} is selected", p.Name);
                        selectedPropertyList.Add(p.Name);
                    }
                }
            }

            ViewBag.ActivityID = activityID;
            int expertSubjectID = -1;
            if (Roles.IsUserInRole("ExpertJudge")) //Only display expert judge's subject in the dropdown list.
            {
                var expert = db.ExpertJudges.Find(Membership.GetUser().UserName);
                expertSubjectID = expert.ExpertGroup.SubjectID!=null?(int)expert.ExpertGroup.SubjectID:-1;
                ViewBag.SubjectID = new SelectList(db.Subjects.Where(s => s.ActivityID == activityID&&s.ID==expertSubjectID), "ID", "Name");
            }
            else
            {
                ViewBag.SubjectID = new SelectList(db.Subjects.Where(s => s.ActivityID == activityID), "ID", "Name");
            }

            var propertInfos = GetArchiveProperties<GetArchiveList_Result>();
            List<ArchiveProperty> archPropList = new List<ArchiveProperty>();
            for (int i = 0; i < propertInfos.Count; i++)
            {
                archPropList.Add(new ArchiveProperty() { Id = i, Name = propertInfos[i].Name, LocalName = Utility.Translate<PessResources.Archive>(propertInfos[i].Name) });
            }

            ExportArchiveListModel model = new ExportArchiveListModel();
            var archives = db.GetArchiveList(activityID).AsEnumerable();//db.Archives.Where(a => a.Subject.ActivityID == activityID);
            if (subjectID > 0)
            {
                archives = archives.Where(a => a.SubjectID == subjectID);
            }
            if (Roles.IsUserInRole("CountyAdmin"))
            {
                string countyCode = Utility.GetCountyCode();
                archives = archives.Where(a => a.CountyCode == countyCode);
            }
            if (Roles.IsUserInRole("ExpertJudge"))
            {
                archives = archives.Where(a => a.SubjectID == expertSubjectID);
            }
            
            model.Archives = archives;
            model.Properties = archPropList;
            model.SelectedProperties = selectedPropertyList.ToArray();
            model.SelectedSubjectID = subjectID;

            return View(model);

        }
        //This is a backup
        //public ActionResult ExportArchiveList(int activityID, List<ArchiveProperty> properties,int subjectID=-1)
        //{
        //    List<string> selectedPropertyList = new List<string>();
        //    if (properties != null)
        //    {
        //        foreach (var p in properties)
        //        {
        //            if (p.IsSelected)
        //            {
        //                //Debug.WriteLine("Property {0} is selected", p.Name);
        //                selectedPropertyList.Add(p.Name);
        //            }
        //        }
        //    }

        //    ViewBag.ActivityID = activityID;
        //    ViewBag.SubjectID = new SelectList(db.Subjects.Where(s => s.ActivityID == activityID), "ID", "Name");
            
        //    var propertInfos = GetArchiveProperties();
        //    List<ArchiveProperty> archPropList = new List<ArchiveProperty>();
        //    for (int i = 0; i < propertInfos.Count; i++)
        //    {
        //        archPropList.Add(new ArchiveProperty() { Id = i, Name = propertInfos[i].Name, LocalName = Translate(propertInfos[i].Name) });
        //    }

        //    ExportArchiveListModel model = new ExportArchiveListModel();
        //    var archives=db.Archives.Where(a => a.Subject.ActivityID == activityID);
        //    if (subjectID > 0)
        //    {
        //        archives = archives.Where(a => a.SubjectID == subjectID);
        //    }
        //    if (Roles.IsUserInRole("CountyAdmin"))
        //    {
        //        string countyCode = Utility.GetCountyCode();
        //        archives = archives.Where(a => a.CountyCode == countyCode);
        //    }
        //    model.Archives = archives;
        //    model.Properties = archPropList;
        //    model.SelectedProperties = selectedPropertyList.ToArray();
        //    model.SelectedSubjectID = subjectID;

        //    return View(model);

        //}



        public ActionResult Report(int activityID, int subjectID = -1, string[] selectedProperties = null)
        {
            var query = db.GetArchiveList(activityID).AsEnumerable();//db.Archives.Where(a => a.Subject.ActivityID == activityID);
            if (subjectID > 0)
            {
                query = query.Where(a => a.SubjectID == subjectID);
            }
            if (Roles.IsUserInRole("CountyAdmin"))
            {
                string countyCode = Utility.GetCountyCode();
                query = query.Where(a => a.CountyCode == countyCode);
            }
            //return CreateReport(query,new DoddleReport.Writers.ExcelReportWriter(), selectedProperties);
            Activity activity=db.Activities.Find(activityID);
            Subject subject=db.Subjects.Find(subjectID);
            string subTitle=string.Format("{0}:{1}",subject!=null?subject.Name:"",activity.Name);
            var report = CreateReport(query, selectedProperties,"档案清单",subTitle);
            IReportWriter writer = new DoddleReport.Writers.ExcelReportWriter();
            return new ReportResult(report, writer, "application/vnd.ms-excel") { FileName = HttpUtility.UrlPathEncode("档案.xls") }; 
        }

        private Report CreateReport(IEnumerable query, string[] selectedProperties = null,string reportTitle=null,string reportSubTitle=null,string reportHeader=null)
        {
            var report = new DoddleReport.Report(query.ToReportSource());

            report.TextFields.Title = reportTitle;// "Products Report";
            report.TextFields.SubTitle = reportSubTitle;// "This is a sample report showing how Doddle Report works";
            report.TextFields.Footer = string.Format("{0}上海市教委教研室",DateTime.Now.ToShortTimeString());
            report.TextFields.Header = reportHeader;// "What a beautiful day!";

            for (int i = 0; i < report.DataFields.Count; i++)
            {
                if (selectedProperties!=null&&!selectedProperties.Contains(report.DataFields[i].Name))
                {
                    report.DataFields[i].Hidden = true;
                }
                else
                {
                    report.DataFields[i].HeaderText = Utility.Translate<PessResources.Archive>(report.DataFields[i].Name);
                }
            }

            return report;            
        }
           

        public ActionResult ImportReviewFeedbacks(int subjectID)
        {
            ReviewFeedbackListModel model = new ReviewFeedbackListModel();
            model.SubjectID = subjectID;
            var subject = db.Subjects.Find(subjectID);
            model.ActivityName = subject.Activity.Name;
            model.ActivityID = subject.ActivityID;
            model.SubjectName = subject.Name;
            model.Feedbacks = ibl.GetFeedbacks(subjectID);

            return View(model);
        }

        [HttpPost]
        public ActionResult ImportReviewFeedbacks(int subjectID, HttpPostedFileBase file)
        {
            ReviewFeedbackListModel model = new ReviewFeedbackListModel();
            model.SubjectID = subjectID;
            var subject = db.Subjects.Find(subjectID);
            model.ActivityName = subject.Activity.Name;
            model.ActivityID = subject.ActivityID;
            model.SubjectName = subject.Name;

            // Verify that the user selected a file
            if (file != null && file.ContentLength > 0)
            {
                // extract only the fielname
                var fileName = Path.GetFileName(file.FileName);
                // store the file inside ~/App_Data/uploads folder
                var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
                file.SaveAs(path);


                var excel = new ExcelQueryFactory(path);
                //excel.FileName = ;
                excel.DatabaseEngine = DatabaseEngine.Ace;
                excel.AddMapping<FeedbackModel>(m => m.ArchiveSerialNumber, "档案编号");
                excel.AddMapping<FeedbackModel>(m => m.ProjectSN, "立项编号");
                excel.AddMapping<FeedbackModel>(m => m.ReviewFeedback, "反馈意见");
                excel.AddMapping<FeedbackModel>(m => m.Conclusion, "评审结论");

                var feedbackList = from m in excel.Worksheet<FeedbackModel>()
                              select m;

                foreach (var f in feedbackList)
                {                    
                    ibl.AddFeedback(f,subjectID);                        
                }
            }

            model.Feedbacks = ibl.GetFeedbacks(subjectID);

            return View(model);//RedirectToAction("Index", new { activityID = subject.ActivityID });  
        }

        public ActionResult Feedback(string serialNumber)
        {
            ViewBag.ArchiveID=db.Archives.Where(a => a.SerialNumber==serialNumber).FirstOrDefault().ID;
            return View(ibl.ArchiveFeedback(serialNumber));
        }

        public ActionResult EditFeedback(string serialNumber)
        {
            return View(ibl.ArchiveFeedback(serialNumber));
        }

        [HttpPost]
        public ActionResult EditFeedback(FeedbackModel model)
        {
            if (!ibl.UpdateFeedback(model))
            {
                return View(model);
            }
            else
            {
                return RedirectToAction("Feedback", "Archive", new {serialNumber=model.ArchiveSerialNumber });
            }
        }

        public FileResult DownloadArchives(int activityID, int subjectID)
        {
            var archives = db.Archives.Where(a => a.SubjectID == subjectID && a.Subject.ActivityID == activityID);
            //create zip file
            string filename;
            string targetfile;
            using (ZipFile zip = new ZipFile(System.Text.Encoding.GetEncoding(936)))
            {
                foreach (var archive in archives)
                {
                    var path = Path.Combine(Server.MapPath("~/App_Data/Archives/"), activityID.ToString(), archive.ID.ToString());
                    if (Directory.Exists(path))
                    {
                        zip.AddDirectory(path, archive.Subject.Name + archive.SerialNumber + archive.TeacherName);
                    }
                }
                filename = Guid.NewGuid().ToString() + ".zip";
                if(!Directory.Exists(Server.MapPath("~/App_Data/zipfiles/")))
                {
                    Directory.CreateDirectory(Server.MapPath("~/App_Data/zipfiles/"));
                }
                targetfile = Path.Combine(Server.MapPath("~/App_Data/zipfiles/"), filename);
                zip.Save(targetfile);
                ViewBag.Filename = "~/App_Data/zipfiles/" + filename;
            }
            //return zip file url

            var subject = db.Subjects.Find(subjectID);
            string subjectName = "";
            if (subject != null)
            {
                subjectName = subject.Name;
            }
            else
            {
                subjectName = "请选择学科并点击预览";
            }
            return File(targetfile, Utility.GetMimeType(Path.GetExtension(targetfile)), HttpUtility.UrlEncode(string.Format("{0}.zip",subjectName)));
        }
    }
}